using System;
using System.Linq;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

using Aks.Deployment.SharePoint.Administration.Extensions;

namespace Aks.Deployment.Features
{
	/// <summary>
	/// Timer job that either sets up or tears down the uAKS Accessibility Infrastructure feature.
	/// </summary>
	public class InfrastructureSetupJob : SPJobDefinition
	{
		#region | Fields |

		private const string ActivationJobName = "uAKS Infrastructure Setup";
		private const string DeactivationJobName = "uAKS Infrastructure Cleanup";
		private const string CoreBrowserCapsFile = "uaks.browser";
		private const string CssFriendlyBrowserCapsFile = "uaks-cssfriendly.browser";

		[Persisted]
		private readonly bool _isActivating;

		#endregion


		#region | Initialization |

		/// <summary>
		/// Initializes a new instance of the <see cref="InfrastructureSetupJob"/> class.
		/// </summary>
		public InfrastructureSetupJob()
		{}


		/// <summary>
		/// Initializes a new instance of the <see cref="InfrastructureSetupJob"/> class.
		/// </summary>
		/// <param name="webapp">The web application.</param>
		/// <param name="isActivating">Specifies whether the job is running during feature activation.</param>
		public InfrastructureSetupJob(SPWebApplication webapp, bool isActivating) : base((isActivating) ? ActivationJobName : DeactivationJobName, webapp, null, SPJobLockType.None)
		{
			Title = (isActivating) ? ActivationJobName : DeactivationJobName;
			Schedule = new SPOneTimeSchedule(DateTime.Now.AddHours(-1));
			this._isActivating = isActivating;
		}

		#endregion


		#region | Methods [Public] |

		/// <summary>
		/// Executes the job definition against the content database identified by the specified <paramref name="targetInstanceId"/>.
		/// </summary>
		/// <param name="targetInstanceId">For target types of <see cref="SPContentDatabase"></see> this is the database ID of the content database being processed by the running job. This value is Guid.Empty for all other target types.</param>
		public override void Execute(Guid targetInstanceId)
		{
			// copy app browser files to app_browsers directory
			foreach (var zoneKey in WebApplication.IisSettings)
			{
				// clean up any old files 
				var zone = zoneKey.Value;
				zone.DeleteBrowserCapsFile(CoreBrowserCapsFile);
				zone.DeleteBrowserCapsFile(CssFriendlyBrowserCapsFile);

				// if deactivating, continue to the next zone
				if (!this._isActivating) continue;
				
				// copy new files
				zone.CopyBrowserCapsFileFromFeature(AccessibilityInfrastructure.FeatureDirectory, CoreBrowserCapsFile);
				zone.CopyBrowserCapsFileFromFeature(AccessibilityInfrastructure.FeatureDirectory, CssFriendlyBrowserCapsFile);
			}

			base.Execute(targetInstanceId);
		}

		#endregion

		
		public static void Activate(SPWebApplication app)
		{
			new InfrastructureSetupJob(app, true).ExecuteNow();
		}


		public static void Deactivate(SPWebApplication app)
		{
			new InfrastructureSetupJob(app, false).ExecuteNow();
		}


		public void ExecuteNow()
		{
			// if timer service isn't running, throw exception
			if (Farm.TimerService.Instances.Count < 1)
			{
				throw new SPException("Could not run job. Timer service not found.");
			}

			// remove jobs
			var jobs = (from j in WebApplication.JobDefinitions where j.Name == Name select j).ToArray();
			for (var i = 0; jobs != null && i < jobs.Length; i++)
			{
			    jobs[i].Delete();
			}

			// set schedule and update
			Schedule = new SPOneTimeSchedule(DateTime.Now.AddHours(-2));
			Update();
			WebApplication.Update();
		}
	}
}